package com.shixj.easy.spider.executor;

import com.google.common.base.Strings;
import com.shixj.easy.spider.factory.DefaultChapterFactory;
import com.shixj.easy.spider.factory.DefaultNovelFactory;
import com.shixj.easy.spider.factory.EntityFactory;
import com.shixj.easy.spider.mapper.ChapterMapper;
import com.shixj.easy.spider.mapper.NovelMapper;
import com.shixj.easy.spider.model.*;
import com.shixj.easy.spider.service.RecordService;
import com.shixj.ef.config.FetchConfig;
import com.shixj.ef.core.HttpFetcher;
import com.shixj.ef.vo.FetchResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by shixj on 2018/1/15.
 */
@Service("defultFetchExecutor")
@Slf4j
public class DefaultFetchExecutor implements FetchExecutor {
    @Autowired
    NovelMapper novelMapper;
    @Autowired
    ChapterMapper chapterMapper;

    @Autowired
    RecordService recordService;


    private RegexConfig regexConfig;
    private Long novelId=0L;

    /**
     * 保存小说信息
     *
     * @param result
     */
    private Long saveNovel(FetchResult result) {
        EntityFactory factory = new DefaultNovelFactory();
        Novel novel = (Novel) factory.build(result,regexConfig);
        Novel saved=novelMapper.selectOne(novel);
        if(saved!=null){
            novelMapper.delete(novel);
            chapterMapper.deleteByNovel(saved);
        }
        novelMapper.insert(novel);
        recordService.saveRecord(result, novel);
        return novel.getId();
    }

    /**
     * 保存章节
     *
     * @param result
     * @param novelId
     */
    private void saveNovelChapter(FetchResult result, Long novelId) {
        EntityFactory factory = new DefaultChapterFactory();
        Chapter chapter = (Chapter) factory.build(result,regexConfig);
        chapter.setNovelId(novelId);
        chapterMapper.insert(chapter);
        recordService.saveRecord(result, chapter);
    }
    /**
     * 保存章节(批量)
     *
     * @param results
     */
    private void saveNovelChapterList(List<FetchResult> results) {
        if (novelId > 0L){
            List<Chapter> chapterList=new ArrayList<>();
            List<Record> records=new ArrayList<>();
            for (FetchResult result :results) {
                String url = result.getUrl();
                if (!Strings.isNullOrEmpty(url)) {
                    if (url.matches(regexConfig.getChapterPageRegex())) {
                        EntityFactory factory = new DefaultChapterFactory();
                        Chapter chapter = (Chapter) factory.build(result,regexConfig);
                        chapter.setNovelId(novelId);
                        chapterList.add(chapter);
                        records.add(recordService.buildRecord(result,chapter));
                    }
                }
            }
            if(chapterList!=null&&!chapterList.isEmpty()){
                chapterMapper.batchInsertChapter(chapterList);
                recordService.saveRecords(records);
            }
        }
    }
    /**
     * 获取小说并持久化
     */
    @Override
    public Catalog fetchNovel() {
        HttpFetcher fetcher =
                FetchConfig.bulid(regexConfig.getInitUrl()).setDepth(0).setMax(1).setAsync(false)
                        .setThreadLimit(1)
                        .start();
        for (FetchResult result : fetcher.getFetchResults()) {
            String url = result.getUrl();
            if (!Strings.isNullOrEmpty(url)) {
                if (url.matches(regexConfig.getNovelPageRegex())) {
                    novelId = saveNovel(result);
                    break;
                }
            }
        }
        return null;
    }

    /**
     * 获取章节并持久化
     */
    @Override
    public Chapter fetchChapter() {
        HttpFetcher fetcher =
                FetchConfig.bulid(regexConfig.getInitUrl()).setDepth(1).setAsync(false)
                        .setThreadLimit(20)
                       // .setDepthRegex(0, regexConfig.getNovelPageRegex())
                        .setDepthRegex(1, regexConfig.getChapterPageRegex())
                        .start();
        saveNovelChapterList( fetcher.getFetchResults());
        return null;
    }

    /**
     * 初始化爬虫解析执行器
     *
     * @param config
     * @return
     */
    @Override
    @Transactional
    public FetchExecutor init(RegexConfig config) {
        this.regexConfig=config;
        fetchNovel();
        fetchChapter();
        return this;
    }
}
